﻿
// AssemblyDemonstrationView.cpp: CAssemblyDemonstrationView 类的实现
//

#include "pch.h"
#include "GL/glew.h"
#include "framework.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义，并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "AssemblyDemonstration.h"
#endif

#include "AssemblyDemonstrationDoc.h"
#include "AssemblyDemonstrationView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// 打印矩阵
void printmatrix(glm::mat4 m)
{
    TRACE("Matrix-------------------------------------\n");
    TRACE("%f, %f, %f, %f\n", m[0][0], m[0][1], m[0][2], m[0][3]);
    TRACE("%f, %f, %f, %f\n", m[1][0], m[1][1], m[1][2], m[1][3]);
    TRACE("%f, %f, %f, %f\n", m[2][0], m[2][1], m[2][2], m[2][3]);
    TRACE("%f, %f, %f, %f\n", m[3][0], m[3][1], m[3][2], m[3][3]);
}

// CAssemblyDemonstrationView

IMPLEMENT_DYNCREATE(CAssemblyDemonstrationView, CView)

BEGIN_MESSAGE_MAP(CAssemblyDemonstrationView, CView)
	ON_WM_CREATE()
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEWHEEL()
	ON_WM_SIZE()
    ON_WM_DESTROY()
    ON_WM_MBUTTONDOWN()
    ON_WM_MBUTTONUP()
    ON_WM_MOUSEMOVE()
    ON_WM_TIMER()
    ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()



// CAssemblyDemonstrationView 构造/析构

CAssemblyDemonstrationView::CAssemblyDemonstrationView() noexcept
{
	// TODO: 在此处添加构造代码
	inited = false;
	m_hRC = NULL;
}

CAssemblyDemonstrationView::~CAssemblyDemonstrationView()
{
}

BOOL CAssemblyDemonstrationView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CView::PreCreateWindow(cs);
}

// CAssemblyDemonstrationView 绘图

void CAssemblyDemonstrationView::OnDraw(CDC* /*pDC*/)
{
	CAssemblyDemonstrationDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc || !inited)
		return;

    TRACE("OnDraw\n");
	// TODO: 在此处为本机数据添加绘制代码
	wglMakeCurrent(m_hDC, m_hRC);
	glDrawBuffer(GL_BACK);

	glClearColor(0.3f, 0.4f, 0.5f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	m_Program->Use();
	glm::mat4 projection = m_Camera.GetProjectMatrix(Width, Height);
	m_Program->SetMat4("projection", projection);
	glm::mat4 view = m_Camera.GetViewMatrix();
    printmatrix(view);
	m_Program->SetMat4("view", view);



	for (int i = 0; i < m_Model->layerGroups.size(); i++)
	{
		if (m_Model->layerGroupStates[i]==LayerGroupState::Dropped)
		{
			glm::mat4 dropedModel = glm::mat4(1.0f);
			dropedModel = glm::translate(dropedModel, glm::vec3(0.0f, 0.0f, 0.0f));
			dropedModel = glm::scale(dropedModel, glm::vec3(0.1f, 0.1f, 0.1f));
			m_Program->SetMat4("model", dropedModel);
			m_Model->DrawLayerGroup(*m_Program, m_Model->layerGroups[i]);
		}
	}

	if (m_Model->layerGroupStates[num]==LayerGroupState::Dropping)
	{
		glm::mat4 model = glm::mat4(1.0f);
		if (z < 0.0)
		{
			z = 0.0;
		}
		model = glm::translate(model, glm::vec3(0.0f, 0.0f, z)); // translate it down so it's at the center of the scene
		model = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f));	// it's a bit too big for our scene, so scale it down
		m_Program->SetMat4("model", model);
		m_Model->DrawLayerGroup(*m_Program, m_Model->layerGroups[num]);
	}
	

	glFlush();
	SwapBuffers(m_hDC);
	wglMakeCurrent(m_hDC, NULL);
}

// CAssemblyDemonstrationView 诊断

#ifdef _DEBUG
CAssemblyDemonstrationDoc* CAssemblyDemonstrationView::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAssemblyDemonstrationDoc)));
	return (CAssemblyDemonstrationDoc*)m_pDocument;
}
#endif //_DEBUG


// 开启抗锯齿
void CAssemblyDemonstrationView::EnableAntialias()
{
	glEnable(GL_LINE_SMOOTH);
	glEnable(GL_POLYGON_SMOOTH);
	glEnable(GL_DITHER);
	glEnable(GL_POINT_SMOOTH);
	glEnable(GL_MULTISAMPLE_ARB);
}

void CAssemblyDemonstrationView::Setup()
{
	if (inited) return;

	if (!m_hRC)
	{
		m_hRC = wglCreateContext(m_hDC);
		VERIFY(wglMakeCurrent(m_hDC, m_hRC));

		glewInit();

		glClearColor(0, 0, 0, 0);

		EnableAntialias();

		glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
		glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
		glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);

		glEnable(GL_DEPTH_TEST);
		glEnable(GL_DEPTH_RANGE);
		glEnable(GL_CULL_FACE);
		glCullFace(GL_BACK);
		glDepthMask(GL_TRUE);
		glDepthFunc(GL_LEQUAL);

		glShadeModel(GL_SMOOTH);


		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
		glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);


		//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

		glPolygonMode(GL_FRONT, GL_FILL);
		//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

		glMatrixMode(GL_MODELVIEW);

		CRect rect;
		GetClientRect(rect);
		Height = rect.Height();
		Width = rect.Width();
	}
	else {
		wglMakeCurrent(m_hDC, m_hRC);
	}

	InitGL();
	//_InitGraphic();

	m_Model = new  ModelLoader("F:\\360MoveData\\Users\\Administrator\\Desktop\\LearnOpenGL-master\\LearnOpenGL-master\\resources\\objects\\eee\\eee.obj");
	num = m_Model->layerGroups.size() - 1;

	m_Program = new ADProgram();

	wglMakeCurrent(NULL, NULL);

	SetTimer(1, 100, NULL); // 100ms定时,ID为1
	inited = true;
}

void CAssemblyDemonstrationView::InitGL()
{
	if (false == inited)
		return;

	RECT Rect;
	this->GetClientRect(&Rect);
	Width = Rect.right - Rect.left;
	Height = Rect.bottom - Rect.top;
	glViewport(0, 0, Width, Height);
}

// CAssemblyDemonstrationView 消息处理程序
int CAssemblyDemonstrationView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	//m_hRC = NULL;
	m_hDC = ::GetDC(m_hWnd);

	static PIXELFORMATDESCRIPTOR pfd = {
		sizeof(PIXELFORMATDESCRIPTOR),
		1,
		PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA,
		24, // 24-bit color depth  
		0,0,0,0,0,0, // color bits ignored
		0, // no alpha buffer 
		0, // shift bit ignored  
		0, // no accumulation buffer 
		0,0,0,0, // accum bits ignored  				
		32, // 32-bit z-buffer   
		0, // no stencil buffer
		0, // no auxiliary buffer 
		PFD_MAIN_PLANE/*PFD_OVERLAY_PLANE*/, // main layer
		0, // reserved  
		0,0,0 // layer masks ignored  
	};

	const int nPixelFormat = ChoosePixelFormat(m_hDC, &pfd);
	SetPixelFormat(m_hDC, nPixelFormat, &pfd);

	return 0;
}

// 不要重绘背景
BOOL CAssemblyDemonstrationView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	return false;
	//return CView::OnEraseBkgnd(pDC);
}


BOOL CAssemblyDemonstrationView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_Camera.ProcessMouseScroll(zDelta);
	Invalidate();

	return CView::OnMouseWheel(nFlags, zDelta, pt);
}


void CAssemblyDemonstrationView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	// TODO: 在此处添加消息处理程序代码
	wglMakeCurrent(m_hDC, m_hRC);
	Width = cx;
	Height = cy;
	glViewport(0, 0, Width, Height);
	wglMakeCurrent(NULL, NULL);
}


void CAssemblyDemonstrationView::OnDestroy()
{
    CView::OnDestroy();

    // TODO: 在此处添加消息处理程序代码
    if (inited)
    {
        wglDeleteContext(m_hRC);
        ::ReleaseDC(m_hWnd, m_hDC);
        delete m_Model;
        delete m_Program;
        m_Model = NULL;
        m_Program = NULL;
        m_hDC = nullptr;
        m_hRC = nullptr;
        inited = false;
    }
}


void CAssemblyDemonstrationView::OnMButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    m_LastX = point.x;
    m_LastY = point.y;

    TRACE("Mouse middle button push down\n");
    CView::OnMButtonDown(nFlags, point);
}


void CAssemblyDemonstrationView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    m_LastX = point.x;
    m_LastY = point.y;

    TRACE("Mouse left button push down\n");
    CView::OnLButtonDown(nFlags, point);
}


void CAssemblyDemonstrationView::OnMButtonUp(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    TRACE("Mouse Button push up\n");
    CView::OnMButtonUp(nFlags, point);
}


void CAssemblyDemonstrationView::OnMouseMove(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    if (MK_MBUTTON == (nFlags & MK_MBUTTON)) // 鼠标中键平移
    {
        int xpos = point.x;
        int ypos = point.y;

        int xdis = m_LastX - xpos;
        int ydis = ypos - m_LastY; // reversed since y-coordinates go from bottom to top

        if (xdis != 0 || ydis != 0)
        {
            //TRACE("Mouse move x:%d, y:%d\n", xdis, ydis);
            m_LastX = xpos;
            m_LastY = ypos;
            m_Camera.ProcessTranslate(xdis, ydis, Width, Height);

            Invalidate();
        }
    }
    else if (MK_LBUTTON == (nFlags & MK_LBUTTON)) // 鼠标左键旋转
    {
        TRACE("OnMouseMove Rotate model\n");
        int xpos = point.x;
        int ypos = point.y;

        float xdis = float(m_LastX - xpos);
        float ydis = float(m_LastY - ypos); // reversed since y-coordinates go from bottom to top

        if (xdis != 0 || ydis != 0)
        {
            //TRACE("Mouse move x:%d, y:%d\n", xdis, ydis);
            m_LastX = xpos;
            m_LastY = ypos;
            m_Camera.ProcessMouseMovement(xdis, ydis);

            Invalidate();
        }
    }

    CView::OnMouseMove(nFlags, point);
}


BOOL CAssemblyDemonstrationView::PreTranslateMessage(MSG* pMsg)
{
    // TODO: 在此添加专用代码和/或调用基类
    float cameraSpeed = 50.0f / 600.0f;
    if (pMsg->message == WM_KEYDOWN)
    {
        switch (pMsg->wParam)
        {
        case VK_UP:
            m_Camera.ProcessMouseMovement(0, -cameraSpeed);
            break;
        case VK_DOWN:
            m_Camera.ProcessMouseMovement(0, cameraSpeed);
            break;
        case VK_LEFT:
            m_Camera.ProcessMouseMovement(-cameraSpeed, 0);
            break;
        case VK_RIGHT:
            m_Camera.ProcessMouseMovement(cameraSpeed, 0);
            break;
        case VK_SHIFT:
            //m_isShiftDown = true;
            break;
        case 't':
        case 'T':
            //Test();
            break;
        case 'f':
        case 'F':
            //ZoomToFit();
            break;
        case VK_ADD:                        // 数字键盘 +
            if (m_FallingSpeed < 10.0f)
                m_FallingSpeed += 0.2;
            break;

        case VK_SUBTRACT:                   // 数字键盘 -
            if (m_FallingSpeed > 0.2f)
                m_FallingSpeed -= 0.2;
            break;

        case VK_SPACE:                      // 空格
            if (false == m_IsPause)
            {
                KillTimer(1);
                m_IsPause = true;
            }
            else
            {
                SetTimer(1, 100, NULL); // 100ms定时,ID为1
                m_IsPause = false;
            }
            break;
        default:
            break;
        }

        Invalidate();
    }

    if (pMsg->message == WM_KEYUP)
    {
        switch (pMsg->wParam)
        {
        case VK_SHIFT:
            //m_isShiftDown = false;
            break;
        default:
            break;
        };
    }

    return CView::PreTranslateMessage(pMsg);
}

void CAssemblyDemonstrationView::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (z > 0)
	{
		m_Model->layerGroupStates[num] = LayerGroupState::Dropping;
		z -= m_FallingSpeed;
		Invalidate(false);
	}
	else
	{
		m_Model->layerGroupStates[num] = LayerGroupState::Dropped;
		z = 10.0;
		if (num > 0)
		{
			num -= 1;
		}
		else
		{
			KillTimer(1);
		}
	}

	CView::OnTimer(nIDEvent);
}